<?php


namespace App\Services;


use App\Models\Role;
use App\Utils\Code;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class RoleService extends BaseService
{
    /**
     * 创建数据
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function store(array $params) {
        if (!$this->checkParams($params)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($params){
            $model = new Role();
            if (Role::where('title', $params['title'])->first()) {
                throw new \Exception('该角色已经存在', Code::EXIST_REPEAT);
            }
            $model->title = $params['title'];
            if (isset($params['remarks'])) {
                $model->remarks = $params['remarks'];
            }
            if (isset($params['status']) && is_numeric($params['status'])){
                $model->status = (int)$params['status'];
            }
            if (isset($params['menus']) && $params['menus']) {
                $model->save();
                $menus = [];
                foreach ($params['menus'] as $menu) {
                    if (isset($menu['permission']) && $menu['permission']) {
                        $menus[$menu['id']] = ['permission' => $menu['permission']];
                    } else {
                        $menus[] = $menu['id'];
                    }
                }
                $model->menus()->sync($menus);
                return true;
            } else {
                return $model->save();
            }
        });
    }

    /**
     * 数据信息
     * @param $id
     * @param bool $simple
     * @param bool $abnormal
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function show($id, $abnormal = true) {
        $model = Role::where('id', $id)
            ->with(['menus'])
            ->first();
        if (!$model && $abnormal){
            throw new \Exception('不存在的角色ID', Code::EMPTY_DATA);
        }
        return $model;
    }

    /**
     * 更新数据
     * @param $id
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function update($id, array $params) {
        if (!$this->checkParams($params, true)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($id, $params){
            $model = $this->show($id);
            if (Role::where('title', $params['title'])->where('id', '<>', $id)->first()) {
                throw new \Exception('该角色已经存在', Code::EXIST_REPEAT);
            }
            $model->title = $params['title'];
            if (isset($params['remarks'])) {
                $model->remarks = $params['remarks'];
            }
            if (isset($params['status']) && is_numeric($params['status'])){
                $model->status = (int)$params['status'];
            }
            if (isset($params['menus'])) {
                if (is_array($params['menus']) && $params['menus']) {
                    $menus = [];
                    foreach ($params['menus'] as $menu) {
                        if (isset($menu['permission']) && $menu['permission']) {
                            $menus[$menu['id']] = ['permission' => $menu['permission']];
                        } else {
                            $menus[] = $menu['id'];
                        }
                    }
                    $model->menus()->detach();
                    $model->menus()->sync($menus);
                } else {
                    $model->menus()->delete();
                }
            }
            $model->save();
            return $this->show($id);
        });
    }

    /**
     * 删除数据
     * @param $id
     * @return mixed
     * @throws \Exception
     */
    public function destroy($id) {
        if (!$this::$admin) {
            throw new \Exception('你没有权限删除角色', Code::LACK_OF_CONDITIONS);
        }
        $model = $this->show($id);
        return DB::transaction(function () use ($model) {
            DB::table('bind_role_menu')->where('role_id', $model->id)->delete();
            return $model->delete();
        });
    }

    /**
     * 数据分页
     * @param array $params
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function lists(array $params = []) {
        if (isset($params['mode']) && $params['mode'] == 'select') {
            $model = Role::select(['id', 'title']);
        } else {
            $model = Role::with(['menus']);
        }
        if (isset($params['title']) && $params['title']) {
            $model = $model->where('title', 'like', '%'.$params['title'].'%');
        }
        if (isset($params['status']) && is_numeric($params['status'])) {
            $model = $model->where('status', (int)$params['status']);
        }
        $lists = $model->get();
        foreach ($lists as $list) {
            foreach ($list->menus as $menu) {
                if (!is_array($menu->permission) && $menu->permission) {
                    $menu->permission = explode(',', $menu->permission);
                } else {
                    $menu->permission = [];
                }
            }
        }
        return $lists;
    }

    /**
     * 验证参数
     * @param array $params
     * @param bool $isUpdate
     * @return array
     * @throws \Exception
     */
    private function checkParams(array $params, $isUpdate = false){
        $rules = [
            'title' => ['bail', 'required', 'string', 'between:1,20'],
            'remarks' => ['bail', 'nullable', 'string', 'between:1,200'],
            'status' => ['bail', 'integer', 'in:0,1']
        ];
        if ($isUpdate){
            // 删除必选条件
            foreach ($rules as $field => &$rule){
                if (isset($rule[1]) && $rule[1] == 'required') {
                    unset($rule[1]);
                }
            }
        }
        $validator = Validator::make($params, $rules, [], [
            'title' => '角色名称',
            'remarks' => '备注',
            'status' => '可用状态'
        ]);
        if ($validator->fails()) {
            throw new \Exception($validator->errors()->first(), Code::PARAMETER_ERROR);
        }
        return $params;
    }
}
